package net.jueb.custom.protocol;

import net.jueb.custom.pojo.NError;
import net.jueb.custom.pojo.NMsg;
import net.jueb.custom.pojo.NError.NErrorCode;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.util.CharsetUtil;

public class NMsgDecoder extends LengthFieldBasedFrameDecoder{
	
	public NMsgDecoder()
	{
		/**
		 * 使用LengthFieldBasedFrameDecoder作为decoder实现，
		 * LengthFieldBasedFrameDecoder构造函数，
		 * 第一个参数为信息最大长度，超过这个长度回报异常，
		 * 第二参数为长度属性的起始（偏移）位，我们的协议中长度是0到第3个字节，所以这里写0，
		 * 第三个参数为“长度属性”的长度，我们是4个字节，所以写4，
		 * 第四个参数为长度调节值，在总长被定义为包含包头长度时，修正信息长度，
		 * 第五个参数为跳过的字节数，根据需要我们跳过前4个字节，以便接收端直接接受到不含“长度属性”的内容。
		 */
		super(Integer.MAX_VALUE, 0, 4, 0,4);
	}
	/**
	 * 重写LengthFieldBasedFrameDecoder的半包处理方法，此方法的返回值会直接给父类的protected final void decode加入到out里面
	 */
	@Override
	protected Object decode(ChannelHandlerContext ctx, ByteBuf in0) throws Exception {
		ByteBuf in=(ByteBuf) super.decode(ctx, in0);
		if(in==null)
		{
			return in;
		}
		
		/**
		 * 解析head
		 */
		byte head;//一个字节
		if (in.isReadable()) 
		{//是否有数据可读，如果不能读取，则回滚到读取前的位置并返回
            head=in.readByte();
            if(head!=NMsg.head)
            {
            	return new NError(NErrorCode.Unkonwn_Protocol, "未知协议");
            }
        }else
        {
        	return new NError(NErrorCode.Unkonwn_Protocol, "未知协议");
        }
		
		/**
		 * 解析secondProtocolFlag
		 */
		byte secondProtocolFlag;//一个字节
		if (in.isReadable()) 
		{//是否有数据可读，如果不能读取，则回滚到读取前的位置并返回
			secondProtocolFlag=in.readByte();
        }else
        {
        	return new NError(NErrorCode.SecondProtocolType_NotFound, "二层协议标记未发现");
        }
		
		/**
		 * 解析pojoName
		 */
		byte pojoNameLength;//名字长度占一个字节
		if (in.isReadable()) 
		{//是否有数据可读，如果不能读取，则回滚到读取前的位置并返回
			pojoNameLength=in.readByte();
        }else
        {
        	return new NError(NErrorCode.PojoNameLength_NotFound, "数据名称长度未发现");
        }
		
		byte[] pojoName;
		if (in.isReadable(pojoNameLength)) 
		{//是否有数据可读，如果不能读取，则回滚到读取前的位置并返回
			pojoName=in.readBytes(pojoNameLength).array();
        }else
        {
        	return new NError(NErrorCode.PojoName_NotFound, "数据名称未发现");
        }
		
		/**
		 * 解析pojoData
		 */
		int pojoDataLength;//4个字节
		if (in.isReadable(4)) 
		{//是否有数据可读，如果不能读取，则回滚到读取前的位置并返回
			pojoDataLength=in.readInt();//读取有符合4字节整数
        }else
        {
        	return new NError(NErrorCode.PojoDataLength_NotFound, "数据长度未发现");
        }
		byte[] pojoData;
		if (in.isReadable(pojoDataLength)) 
		{//是否有数据可读，如果不能读取，则回滚到读取前的位置并返回
			pojoData=in.readBytes(pojoDataLength).array();
        }else
        {
        	return new NError(NErrorCode.PojoData_NotFound, "数据未发现");
        }
		NMsg nMsg=new NMsg(secondProtocolFlag, new String(pojoName, CharsetUtil.UTF_8), pojoData);
		return nMsg;
	}
}
